import { drawType, pathType } from './draw-type';
import * as Func from './comm-method';

export const draw = function (canvasEleId, dataFunc, values, option) {
  if (!canvasEleId || !dataFunc) {
    console.log('缺少参数！');
    return;
  }
  let canvasElement = document.getElementById(canvasEleId);
  let ctx = canvasElement.getContext('2d');
  let drawList = dataFunc();
  setTimeout(() => {
    fresh(ctx, drawList, values);
    initEvent(canvasElement, drawList, dataFunc, values, option);
  },100);
  return canvasElement;
};
export const refresh = function (canvasEle, drawList, values) {
  fresh(canvasEle.getContext('2d'), drawList, values);
};
function fresh(ctx, drawList, values) {
  ctx.clearRect(-4000, -4000, 8000, 8000);
  drawList.forEach((drawData, index) => {
    drawData.id = 'drawList' + index;
    ctx.save();
    checkGlobal(ctx, drawData);
    drawCanvasData(ctx, drawData, values);
    ctx.restore();
  });
}

export const initEvent = function (canvasEle, drawList, createInitData, values, option) {
  let totalScale = 1;
  let totalScaleMax = 16;
  let totalScaleMin = 0.25;
  let scale = 1;
  let cx = 0;
  let cy = 0;
  let mouseDown = false;
  let moveFromX = 0;
  let moveFromY = 0;
  let mouseDownX = 0;
  let mouseDownY = 0;
  let deltaX = 0;
  let deltaY = 0;
  //鼠标当前停留的位置图形参数
  let mouseOverParam = null;
  let listeners;
  if (option) {
    listeners = option.listeners;
    if (option.totalScaleMax) {
      totalScaleMax = option.totalScaleMax;
    }
    if (option.totalScaleMin) {
      totalScaleMin = option.totalScaleMin;
    }
  }

  canvasEle.onmousedown = (e) => {
    window.getSelection().empty();
    if (e.button === 0) {
      mouseDown = true;
      moveFromX = e.offsetX;
      moveFromY = e.offsetY;
      mouseDownX = e.offsetX;
      mouseDownY = e.offsetY;
    }
  };
  canvasEle.onmouseout = () => {
    mouseDown = false;
    moveFromX = 0;
    moveFromY = 0;
  };
  canvasEle.onmouseup = (e) => {
    mouseDown = false;
    moveFromX = 0;
    moveFromY = 0;
    let mouseClick = e.offsetX === mouseDownX && e.offsetY === mouseDownY;
    if (e.button === 0 && mouseClick) {
      drawList.forEach((drawData) => {
        if(!drawData.translate){
          drawData.translate = [0,0];
        }
        drawData.children.forEach((drawParam) => {
          let ox = e.offsetX - drawData.translate[0];
          let oy = e.offsetY - drawData.translate[1];
          if (drawParam.checkMouseOver(ox, oy)) {
            if (drawParam.onClick) {
              drawParam.onClick({ event: e ,drawParam: drawParam});
            }
            if (drawParam.type === drawType.TABLE) {
              let tableOffsetX = ox - drawParam.start[0];
              let tableOffsetY = oy - drawParam.start[1];
              drawParam.tableDrawList.forEach((cell) => {
                if (cell.checkMouseOver(tableOffsetX, tableOffsetY)) {
                  if (cell.cell) {
                    cell.onClick({ event: e, drawParam: cell });
                  }
                }
              });
            }
          }
        });
      });
    } else if (e.button === 2) {
      if (listeners && listeners.includes('reset') && createInitData) {
        totalScale = 1;
        totalScaleMax = 16;
        totalScaleMin = 0.25;
        scale = 1;
        cx = 0;
        cy = 0;
        mouseDownX = 0;
        mouseDownY = 0;
        deltaX = 0;
        deltaY = 0;
        if (option && option.totalScaleMax) {
          totalScaleMax = option.totalScaleMax;
        }
        if (option && option.totalScaleMin) {
          totalScaleMin = option.totalScaleMin;
        }
        drawList = createInitData();
        fresh(canvasEle.getContext('2d'), drawList, values);
      }
    }
  };
  if (listeners && listeners.includes('zoom')) {
    canvasEle.onmousewheel = (e) => {
      if (e.deltaY > 0 && totalScale < totalScaleMax) {
        scale = 2;
      } else if (e.deltaY < 0 && totalScale > totalScaleMin) {
        scale = 0.5;
      } else {
        return;
      }
      cx = e.offsetX;
      cy = e.offsetY;
      totalScale *= scale;
      Func.zoom(drawList, { cx: cx, cy: cy, scale: scale, totalScale: totalScale });
      fresh(canvasEle.getContext('2d'), drawList, values);
    };
  }
  //鼠标滑动
  canvasEle.onmousemove = (event) => {
    if (mouseDown && listeners && listeners.includes('move')) {
      deltaX = event.offsetX - moveFromX;
      deltaY = event.offsetY - moveFromY;
      moveFromX = event.offsetX;
      moveFromY = event.offsetY;
      let checkMove = Func.move(drawList, { deltaX: deltaX, deltaY: deltaY });
      //moveData();
      if(checkMove){
        fresh(canvasEle.getContext('2d'), drawList, values);
      }
    } else {
      let findOne = false;
      if (mouseOverParam) {
        if (mouseOverParam.parent) {
          let tableOffsetX = event.offsetX - mouseOverParam.parent.start[0] - mouseOverParam.parent.globalTranslate[0];
          let tableOffsetY = event.offsetY - mouseOverParam.parent.start[1]- mouseOverParam.parent.globalTranslate[1];
          if (mouseOverParam.onClick && mouseOverParam.checkMouseOver(tableOffsetX, tableOffsetY)) {
            findOne = true;
          } else {
            mouseOverParam = null;
          }
        } else if (mouseOverParam.checkMouseOver(event.offsetX - mouseOverParam.globalTranslate[0], event.offsetY- mouseOverParam.globalTranslate[1])) {
          if (mouseOverParam.onClick) {
            findOne = true;
          }
          if (mouseOverParam.onMousemove) {
            mouseOverParam.onMousemove({ event: event });
          }
        } else {
          if (mouseOverParam.onMouseout) {
            mouseOverParam.onMouseout({ event: event,drawParam: mouseOverParam });
          }
          mouseOverParam = null;
        }
      } else {
        drawList.forEach((drawData) => {
          if(!drawData.translate){
            drawData.translate = [0,0];
          }
          let ox = event.offsetX - drawData.translate[0];
          let oy = event.offsetY - drawData.translate[1];
          drawData.children.forEach((drawParam) => {
            if (drawParam.name !== 'background' && drawParam.checkMouseOver(ox, oy)) {
              if (drawParam.type === drawType.TABLE) {
                let tableOffsetX = ox - drawParam.start[0];
                let tableOffsetY = oy - drawParam.start[1];
                drawParam.tableDrawList.forEach((cell) => {
                  if (cell.checkMouseOver(tableOffsetX, tableOffsetY)) {
                    if (cell.onClick) {
                      mouseOverParam = cell;
                      findOne = true;
                    }
                  }
                });
              } else {
                mouseOverParam = drawParam;
                if (drawParam.onClick) {
                  findOne = true;
                }
                if (drawParam.onMouseover) {
                  drawParam.onMouseover({ event: event,drawParam: drawParam });
                }
                if (drawParam.onMousemove) {
                  drawParam.onMousemove({ event: event,drawParam: drawParam });
                }
              }
            }
          });
        });
      }
      if (findOne) {
        canvasEle.style.cursor = 'pointer';
      } else {
        canvasEle.style.cursor = 'default';
      }
    }
  };
  canvasEle.oncontextmenu = (event) => event.preventDefault();
};

function drawCanvasData(ctx, drawData, values) {
  let drawList = drawData.children;
  if (!drawList || drawList.length === 0) {
    return;
  }
  drawList.forEach((drawParam, index) => {
    if(!drawParam){
      return;
    }
    ctx.save();
    drawParam.setGlobalTranslate(drawData.translate);
    checkGlobal(ctx, drawParam);
    drawParam.id = drawData.id + '-' + index;
    //复制父级的 样式，文字样式
    if (!drawParam.isClearParentStyle) {
      drawParam.style = Object.assign({}, drawData.style, drawParam.style);
      drawParam.fontStyle = Object.assign({}, drawData.fontStyle, drawParam.fontStyle);
    }
    if (!drawParam.type) {
      console.log('没有 type');
      drawParam.type = drawData.type;
    }
    drawCanvas(ctx, drawParam, values);
    ctx.restore();
  });
}

function drawCanvas(ctx, drawParam, values) {
  if (drawParam.checkHide !== undefined && drawParam.checkHide({ drawParam: drawParam })) {
    //根据回调函数，决定是否需要忽略绘图
    return;
  }
  if (!values) {
    console.log('没有数据信息');
  }
  ctx.save();
  let attr = { ...drawParam.style };
  if(drawParam.checkStyle){
    Object.assign(attr,drawParam.checkStyle({drawParam: drawParam,values: values}))
  }
  if (drawParam.getPositionAttribute) {
    drawParam.getPositionAttribute(attr);
  }
  if (drawParam.type === drawType.RECT || drawParam.type === drawType.LIMIT) {
    drawRect(ctx, drawParam, attr);
  } else if (drawParam.type === drawType.TRIANGLE) {
    drawTriangle(ctx, drawParam, attr);
  } else if (drawParam.type === drawType.CIRCLE || drawParam.type === drawType.ELLIPSE) {
    drawCircle(ctx, drawParam, attr);
  } else if (drawParam.type === drawType.LINE) {
    drawLine(ctx, drawParam, attr);
  } else if (drawParam.type === drawType.POLYGON || drawParam.type === drawType.POLYLINE) {
    drawPoly(ctx, drawParam, attr);
  } else if (drawParam.type === drawType.ARC) {
    drawArc(ctx, drawParam, attr);
  } else if (drawParam.type === drawType.PATH) {
    drawPath(ctx, drawParam, attr);
  } else if (drawParam.type === drawType.TABLE) {
    let drawList = drawParam.getTableDrawList();
    //列表画图
    ctx.translate(drawParam.start[0], drawParam.start[1]);
    drawList.forEach((param) => {
      drawCanvas(ctx, param, values);
    });
  }else if(drawParam.type === drawType.IMAGE){
    return;
  }
  ctx.restore();
  if (typeof drawParam.text !== 'undefined') {
    ctx.save();
    drawText(ctx, drawParam.text, values, drawParam);
    ctx.restore();
  }
  drawCanvasData(ctx, drawParam, values);
}
function drawText(ctx, text, values, drawParam) {
  let fontAttr = Func.getFontAttr(drawParam,values);
  let content;
  if (typeof text === 'number') {
    content = text + '';
  } else if (typeof text === 'string') {
    content = Func.findText(text, values);
  } else if (typeof text === 'object') {
    return drawText(ctx, text.text, values, drawParam);
  } else {
    console.error('没有处理的类型' + typeof text);
    return null;
  }
  setFontStyle(ctx, fontAttr);
  if (checkFill(ctx, fontAttr)) {
    ctx.fillText(content, fontAttr.x, fontAttr.y);
  }
  //todo 文字缩放判断
  if (checkStroke(ctx, fontAttr)) {
    ctx.strokeText(content, fontAttr.x, fontAttr.y);
  }
}
function setFontStyle(ctx, fontAttr) {
  ctx.textAlign = fontAttr.textAnchor === 'middle' ? 'center' : fontAttr.textAnchor;
  ctx.textBaseline = fontAttr.dominantBaseline;
  let font = fontAttr.fontSize + 'px';
  if (fontAttr.fontFamily) {
    font += ' ' + fontAttr.fontFamily;
  }
  if (fontAttr.fontWeight) {
    font = fontAttr.fontWeight + ' ' + font;
  }
  ctx.font = font;
  //todo 字体设置
}

function drawPath(ctx, drawParam, attr) {
  let pointList = drawParam.pointList;
  if (pointList.length === 0) {
    return;
  }
  let firstPoint = pointList[0];
  let lastX = 0;
  let lastY = 0;
  ctx.beginPath();
  let beginIndex = 0;
  if (firstPoint.type !== pathType.M && firstPoint.type !== pathType.Rm) {
    ctx.moveTo(lastX, lastY);
  } else {
    beginIndex = 1;
    if (firstPoint.x) {
      lastX = firstPoint.x;
    }
    if (firstPoint.y) {
      lastY = firstPoint.y;
    }
    ctx.moveTo(lastX, lastY);
  }
  for (let i = beginIndex; i < pointList.length; i++) {
    let point = pointList[i];
    if (point.type.desc === pathType.M.desc || point.type.desc === pathType.Rm.desc) {
      lastX = newValue(lastX, point.x, point.type.desc === pathType.Rm.desc);
      lastY = newValue(lastY, point.y, point.type.desc === pathType.Rm.desc);
      ctx.moveTo(lastX, lastY);
    } else if (point.type.desc === pathType.L.desc || point.type.desc === pathType.Rl.desc) {
      lastX = newValue(lastX, point.x, point.type.desc === pathType.Rl.desc);
      lastY = newValue(lastY, point.y, point.type.desc === pathType.Rl.desc);
      ctx.lineTo(lastX, lastY);
    } else if (point.type.desc === pathType.H.desc || point.type.desc === pathType.Rh.desc) {
      lastX = newValue(lastX, point.x, point.type.desc === pathType.Rh.desc);
      lastY = newValue(lastY, point.y, point.type.desc === pathType.Rh.desc);
      ctx.lineTo(lastX, lastY);
    } else if (point.type.desc === pathType.V.desc || point.type.desc === pathType.Rv.desc) {
      lastX = newValue(lastX, point.x, point.type.desc === pathType.Rv.desc);
      lastY = newValue(lastY, point.y, point.type.desc === pathType.Rv.desc);
      ctx.lineTo(lastX, lastY);
    }
    if (point.type.desc === pathType.Z.desc) {
      ctx.closePath();
    }
  }
  if (checkStroke(ctx, attr,drawParam)) {
    ctx.stroke();
  }
  if (checkFill(ctx, attr)) {
    ctx.fill();
  }
}
function newValue(lastValue, newValue, relative) {
  if (newValue === undefined) {
    return lastValue;
  }
  if (relative) {
    return lastValue + newValue;
  } else {
    return newValue;
  }
}

function drawArc(ctx, drawParam, attr) {
  ctx.beginPath();
  ctx.arc(drawParam.ox, drawParam.oy, drawParam.r, drawParam.startArc, drawParam.endArc);
  if (drawParam.closeType === 1) {
    ctx.closePath();
  } else if (drawParam.closeType === 2) {
    ctx.lineTo(drawParam.ox, drawParam.oy);
    ctx.closePath();
  }
  if (checkStroke(ctx, attr,drawParam)) {
    ctx.stroke();
  }
  if (checkFill(ctx, attr)) {
    ctx.fill();
  }
}

//多边形（自动封闭）或折线（自动封闭）
function drawPoly(ctx, drawParam, attr) {
  ctx.beginPath();
  let pointList = drawParam.pointList;
  let firstPoint = pointList[0];
  ctx.moveTo(firstPoint[0], firstPoint[1]);
  for (let i = 1; i < pointList.length; i++) {
    let p = pointList[i];
    ctx.lineTo(p[0], p[1]);
  }
  if (drawParam.type === drawType.POLYGON) {
    ctx.closePath();
  }
  if (checkStroke(ctx, attr,drawParam)) {
    ctx.stroke();
  }
  if (checkFill(ctx, attr)) {
    ctx.fill();
  }
}

function drawLine(ctx, drawParam, attr) {
  ctx.beginPath();
  ctx.moveTo(attr.x1, attr.y1);
  ctx.lineTo(attr.x2, attr.y2);
  if (checkStroke(ctx, attr,drawParam)) {
    ctx.stroke();
  }
}

function drawCircle(ctx, drawParam, attr) {
  let r = attr.r;
  ctx.translate(attr.cx, attr.cy);
  if (drawParam.type === drawType.ELLIPSE) {
    r = attr.rx;
    let scaleY = drawParam.ry / r;
    ctx.scale(1, scaleY);
  }
  ctx.beginPath();
  ctx.arc(0, 0, r, 0, Math.PI * 2);
  ctx.closePath();
  if (checkFill(ctx, attr)) {
    ctx.fill();
  }
  if (checkStroke(ctx, attr,drawParam)) {
    ctx.stroke();
  }
}

function drawTriangle(ctx, drawParam, attr) {
  ctx.beginPath();
  ctx.moveTo(drawParam.x1, drawParam.y1);
  ctx.lineTo(drawParam.x2, drawParam.y2);
  ctx.lineTo(drawParam.x3, drawParam.y3);
  ctx.closePath();
  if (checkFill(ctx, attr)) {
    ctx.fill();
  }
  if (checkStroke(ctx, attr,drawParam)) {
    ctx.stroke();
  }
}

function drawRect(ctx, drawParam, attr) {
  let leanX = 0;
  let leanY = 0;
  if (drawParam.leanX) {
    leanX = drawParam.leanX;
  }
  if (drawParam.leanY) {
    leanY = drawParam.leanY;
  }
  ctx.transform(1, leanX, leanY, 1, 0, 0);
  if (checkFill(ctx, attr)) {
    ctx.fillRect(attr.x, attr.y, attr.width, attr.height);
  }
  if (checkStroke(ctx, attr,drawParam)) {
    ctx.strokeRect(attr.x, attr.y, attr.width, attr.height);
  }
}

function checkFill(ctx, attr) {
  if (attr.fill && attr.fill !== 'none') {
    ctx.fillStyle = attr.fill;
    return true;
  }
  return false;
}
function checkStroke(ctx, attr,drawParam) {
  if (attr.stroke && attr.stroke !== 'none') {
    if(!drawParam && !drawParam.isBorderScale){
      ctx.lineWidth = attr.strokeWidth / drawParam.scale;
    }else {
      ctx.lineWidth = attr.strokeWidth;
    }
    ctx.strokeStyle = attr.stroke;
    ctx.lineCap = attr.lineCap;
    return true;
  }
  return false;
}

//是否全局移动
function checkGlobal(ctx, drawData) {
  if (drawData.translate) {
    let tx = drawData.translate[0];
    let ty = drawData.translate[1];
    ctx.translate(tx, ty);
  }
  if (drawData.rotate) {
    ctx.rotate((drawData.rotate * Math.PI) / 180);
  }
  if (drawData.scale) {
    ctx.scale(drawData.scale, drawData.scale);
  }
}
